﻿/*
 * This file is part of the BF3StatsNet API DLL
 * 
 * The BF3StatsNet DLL is a program created for accessing the API information from http://www.bf3stats.com/api.
 * The purpose of the DLL is to package the json information returned by the website into custom domain objects
 * and hopefully make it easier to use the information when adding BF3 stats on a website or in a program.
 * 
 */

using System;
using System.Collections.Generic;
using System.Net;
using BF3StatsNetApi.BLL;
using Newtonsoft.Json;

namespace BF3StatsNetApi
{
    /// <summary>
    /// Main class for all communication with the BF2Stats.com/API.
    /// The methods in this class are the ones the users of the DLL will be using, to 
    /// get information to use in their own website or application.
    /// 
    /// </summary>
    public sealed class BF3StatsNet
    {
        static BF3StatsNet instance = null;

        private BF3StatsNet()
        {
        }

        public static BF3StatsNet Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new BF3StatsNet();
                }
                return instance;
            }
        }

        /// <summary>
        /// This method will return information about a single player specified by <paramref name="playerName"/>. 
        /// The parameter <paramref name="platform"/> specifies on which platform the player should be found.
        /// </summary>
        /// <param name="platform">A string representing the platform that should be searched for the player in question.</param>
        /// <param name="playerName">The name of the player to be found.</param>
        /// <returns>The returned value is a <see cref="Player"/> object containing information about the player in question. 
        /// If the player is not found the object will be empty.</returns>
        public Player GetPlayerInfo(string platform, string playerName)
        {
            Player pl = new Player();

            pl = (Player)BF3StatsCache.Instance[platform + "_" + playerName.ToLower()];
            if (pl == null)
            {
                try
                {
                    string url = string.Format("http://api.bf3stats.com/{0}/player/player={1}", platform, playerName);
                    var json = new WebClient().DownloadString(url);
                    pl = JsonConvert.DeserializeObject<Player>(json);

                    if (pl.status == "notfound")
                    {
                        throw new BF3StatsException(string.Format("The player '{0}' could not be found.", playerName));
                    }
                    else if (pl.status == "error")
                    {
                        string message = "";
                        switch (pl.error)
                        {
                            case "invalid_platform":
                                message = string.Format("The platform specified '{0}' is not valid.", platform);
                                break;
                            case "invalid_name":
                                message = string.Format("The player specified '{0}' is not valid.", playerName);
                                break;
                            case "private":
                                message = string.Format("The requested information is marked as private.");
                                break;
                        }
                        throw new BF3StatsException(message);
                    }

                    BF3StatsCache.Instance.Set(platform + "_" + playerName.ToLower(), pl, Ckode.Caching.ExpirationType.AbsoluteExpiration, TimeSpan.FromMinutes(5));
                }
                catch (Exception ex)
                {
                    throw new BF3StatsException(ex.Message, ex);
                }
            }

            return pl;
        }

        /// <summary>
        /// This method is used for searching for information about a list of players. 
        /// The players to be found are specified by <paramref name="playerNames"/> and the parameter <paramref name="platform"/>
        /// specifies on which platform the players should be found.
        /// </summary>
        /// <param name="platform">A string representing the platform that should be searched for the player in question.</param>
        /// <param name="playerNames">A comma-seperated list of player names that should be searched for.</param>
        /// <returns>The returned value from the method is a list of <paramref name="Player"/> objects containing information
        /// about the players that were found on the specified platform.</returns>
        public List<Player> GetPlayerList(string platform, string playerNames)
        {
            Player pl = null;
            List<Player> _retList = new List<Player>();
            string listOfNames = string.Empty;

            


            //Run through the list of player names and check the cache for saved information.
            foreach (string name in playerNames.Split(','))
            {
                pl = (Player)BF3StatsCache.Instance.Get(platform + "_" + name.ToLower()); // BF3StatsCache.Instance[platform + "_" + name];
                if (pl != null)
                {
                    _retList.Add(pl);
                }
                else
                {
                    listOfNames += name + ",";
                }
            }

            if (listOfNames != string.Empty)
            {
                try
                {
                    string url = string.Format("http://api.bf3stats.com/{0}/playerlist/players={1}", platform, listOfNames);
                    var json = new WebClient().DownloadString(url);
                    PlayerList plist = JsonConvert.DeserializeObject<PlayerList>(json);

                    if (plist.status == "error")
                    {
                        string message = "";
                        switch (plist.error)
                        {
                            case "invalid_platform":
                                message = string.Format("The platform specified '{0}' is not valid.", platform);
                                break;
                            case "no_player_given":
                                message = string.Format("No player names were specified.");
                                break;
                            case "no_valid_players":
                                message = string.Format("No valid players were specified.");
                                break;
                            case "index_database_error":
                                message = string.Format("Database error - index");
                                break;
                            case "data_database_error":
                                message = string.Format("Database error - data");
                                break;
                            case "too_many_players":
                                message = string.Format("Too many players specified.");
                                break;
                            case "private":
                                message = string.Format("The requested information is marked as private.");
                                break;
                        }
                        throw new BF3StatsException(message);
                    }

                    foreach (Player p in (List<Player>)plist.list)
                    {
                        BF3StatsCache.Instance.Set(platform + "_" + p.name.ToLower(), p, Ckode.Caching.ExpirationType.AbsoluteExpiration, TimeSpan.FromMinutes(5));
                        _retList.Add(p);
                    }

                }
                catch (Exception ex)
                {
                    throw new BF3StatsException(ex.Message, ex);
                }

            }

            return _retList;
        }

        /// <summary>
        /// This method is not implemented yet.
        /// </summary>
        /// <param name="platform"></param>
        /// <param name="playerName"></param>
        public void GetDogtags(string platform, string playerName)
        {
            //string url = string.Format("http://api.bf3stats.com/{0}/dogtags/player={1}", platform, playerName);
            //var json = new WebClient().DownloadString(url);

            throw new NotImplementedException("This method is not implemented yet.");
        }

        /// <summary>
        /// This method is not implemented yet.
        /// </summary>
        /// <param name="platform"></param>
        public void GetOnlinestats(string platform)
        {
            //string url = string.Format("http://api.bf3stats.com/global/onlinestats/");
            //var json = new WebClient().DownloadString(url);

            throw new NotImplementedException("This method is not implemented yet.");
        }
    }

}
